def expandValues(alist):
    for i in range(1,len(alist)):
        if alist[i]=='':
            alist[i]=alist[i-1]
    return alist

def getColIndex1(row_list):
    temp=[]
    col_index =[]

    for i in range(len(row_list)):
        if (type(row_list[i])==float)|(type(row_list[i])==int):
          temp.append(i)

    # 从第二个数开始取，第一个数是课程权重
    for i in range(1,len(temp)):
        col_index.append(temp[i])
    return col_index

def getOperator1(data,row_list,index1=2,index2=4):
    '''
    获取全部权重列表
    :param data:
    :param row_list:
    :param index1: 大指标权重对应行索引
    :param index2: 小指标权重对应行索引
    :return:
    '''
    weight1_temp=expandValues(data.row_values(index1))
    weight2_temp=data.row_values(index2)
    # 寻找该行中所有有值的列索引
    col_index=getColIndex1(row_list)
    weight1=[]
    weight2=[]
    score=[]
    for i in col_index:
        weight1.append(weight1_temp[i])
        weight2.append(weight2_temp[i])
        score.append(row_list[i])

    #扩展课程权重列表，方便后续连乘
    length=len(weight2)
    weight3=[row_list[1]]*length
    return weight1,weight2,weight3,score

def getColIndex2(row_list,c_index1,c_index2):
    '''
    :param row_list: 行数据
    :param c_index1: 所计算小指标第一个数对应列索引
    :param c_index2: 所计算小指标最后一个数对应列索引
    '''
    col_index=[]
    for index,val in enumerate(row_list):
        if (index>=c_index1)&(index<=c_index2):
            if (type(val)==float)|(type(val)==int):
                    col_index.append(index)
    return col_index

def getOperator2(data,row_list,c_index1,c_index2,r_index1=2,r_index2=4):
    '''

    :param data:
    :param row_list: 行数据
    :param c_index1: 所计算小指标第一个数对应列索引
    :param c_index2: 所计算小指标最后一个数对应列索引
    :param r_index1: 大指标权重对应行索引
    :param r_index2: 小指标权重对应行索引
    :return:
    '''
    weight1_temp = expandValues(data.row_values(r_index1))
    weight2_temp=data.row_values(r_index2)
    # 寻找该行中所有有值的列索引
    col_index = getColIndex2(row_list,c_index1,c_index2)


    weight1=[]
    weight2=[]
    score=[]
    if col_index!=[]:
        for i in col_index:
            weight1.append(weight1_temp[i])
            weight2.append(weight2_temp[i])
            score.append(row_list[i])
        # 扩展课程权重列表，方便后续连乘
        length = len(weight2)
        weight3 = [row_list[1]] * length
        return weight1,weight2,weight3,score
    else:
        return 0

def getTotalCompletion(data,class_count,start_index=5):
    '''
    主方法
    :param data:权重表
    :param start_index:出现完成度数据（即第一个课程所在行）的行索引
    :param class_count:学生人数
    :return:
    '''
    end_index=class_count+start_index-1
    raws_list=[]
    for i in range(start_index,end_index+1):
        raws_list.append(data.row_values(i))

    completion1=0
    completion2=0

    for i in raws_list:
        # 注意getOperator的默认参数，指标值所在行索引
        w1,w2,w3,score=getOperator1(data,i)
        temp_completion1=0
        temp_completion2=0
        for j in range(len(w1)):
            temp1=w1[j]*w2[j]*w3[j]*score[j]
            temp2=w1[j]*w2[j]*w3[j]
            temp_completion1+=temp1
            temp_completion2+=temp2
        completion1+=temp_completion1
        completion2+=temp_completion2
    completion=completion1/completion2
    return completion

def getPartCompletion(data,class_count,big_indicator_index,small_indicator_count_list,start_index=5):
    '''
    :param data: 所在文件
    :param class_count: 课程数量
    :param big_indicator_index:大目标索引，从1开始依次对应1-6
    :param small_indicator_count_list: 每个大指标包含的小目标组成的列表
    :param start_index: 第一个课程数据所在行
    :return: 某个大指标完成度
    '''
    end_index=class_count+start_index-1
    raws_list=[]
    for i in range(start_index,end_index+1):
        raws_list.append(data.row_values(i))

    # 1--》第一列是表头结束位置
    # sum(small_indicator_count_list[:big_indicator_index-1])--》经过了前面的多少列
    # 1--》下一列就是开始列
    start_col=1+sum(small_indicator_count_list[:big_indicator_index-1])+1
    end_col=start_col+small_indicator_count_list[big_indicator_index-1]-1

    completion1 = 0
    completion2 = 0

    for i in raws_list:
        # 注意getOperator的默认参数，指标值所在行索引
        if getOperator2(data,i,start_col,end_col)==0:
            continue
        else:
            w1,w2,w3,score=getOperator2(data,i,start_col,end_col)
            temp_completion1=0
            temp_completion2=0
            for j in range(len(w1)):
                temp1=w1[j]*w2[j]*w3[j]*score[j]
                temp2=w1[j]*w2[j]*w3[j]
                temp_completion1+=temp1
                temp_completion2+=temp2
            completion1+=temp_completion1
            completion2+=temp_completion2
    completion=completion1/completion2
    return completion

if __name__=='__main__':
    import xlrd
    file_path = 'excel_output/static/模板_课程与指标对应关系.xlsx'
    excel = xlrd.open_workbook(file_path)
    data = excel.sheet_by_index(0)
    # getCompletion方法还包含两个默认参数start_index和
    total_completion=getTotalCompletion(data,class_count=5)
    # 每个指标有多少个小指标的列表，表示4个6
    small_indicator_count_list=[4]*6
    part_completion=getPartCompletion(data,class_count=5,big_indicator_index=1,small_indicator_count_list=small_indicator_count_list)
    print(part_completion)

    